home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1995-05-04 | 9.1 KB | 276 lines | [TEXT/.Ob4] |
- Syntax10.Scn.Fnt
- FoldElems
- Syntax10.Scn.Fnt
- (*---------------------------------------------------------------------
- Extracts class interfaces from a source module (record types with type-bound procedures)
- Class.Show *
- shows the interfaces of all record types in the marked source text.
- Class.Show modulename.typename
- shows the interface of the specified type.
- Class.Show ^
- shows the interface of the specified type. The selection may be
- - a (non-imported) type name in the source text of the declaring module.
- - a combination modulename.typename in any text.
- ----------------------------------------------------------------------*)
- Syntax10i.Scn.Fnt
- StampElems
- Alloc
- 4 May 95
- Syntax10b.Scn.Fnt
- Documentation
- MODULE Class; (** HM 26-11-93 /
- IMPORT
- Oberon, Viewers, Texts, TextFrames, MenuViewers;
- CONST
- StdMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Store";
- TAB = 9X; CR = 0DX;
- eot = 0; procedure = 1; array = 2; record = 3; pointer = 4; end = 5; colon = 6;
- lparen = 7; rparen = 8; semicolon = 9; eql = 10; arrow = 11; star = 12;
- ident = 13; none = 99;
- TYPE
- Name = ARRAY 64 OF CHAR;
- Class = POINTER TO ClassDesc;
- Method = POINTER TO MethodDesc;
- ClassDesc = RECORD
- name: Name;
- kind: INTEGER;
- beg, end: LONGINT;
- methods: Method;
- link, next: Class
- END;
- MethodDesc = RECORD
- beg, end: LONGINT;
- next: Method
- END;
- ch: CHAR;
- sym, lastSym: INTEGER;
- pos, lastPos: LONGINT;
- B: Texts.Buffer;
- TMod, TOut: Texts.Text;
- R: Texts.Reader;
- W: Texts.Writer;
- id: Name;
- lineBeg: LONGINT;
- lastID: Name;
- lastIDline: LONGINT;
- type: Name;
- classes: Class;
- (* scanner *)
- PROCEDURE Ch;
- BEGIN
- Texts.Read(R, ch); INC(pos)
- END Ch;
- PROCEDURE Start(n: LONGINT);
- BEGIN
- pos := n; Texts.OpenReader(R, TMod, pos)
- END Start;
- PROCEDURE Comment;
- BEGIN
- LOOP
- IF R.eot THEN RETURN
- ELSIF ch = "*" THEN Ch; IF ch = ")" THEN Ch; RETURN END
- ELSIF ch = "(" THEN Ch; IF ch = "*" THEN Ch; Comment END
- ELSE Ch
- END
- END
- END Comment;
- PROCEDURE Ident;
- VAR i: INTEGER;
- BEGIN sym := ident; i := 0;
- REPEAT id[i] := ch; Ch; INC(i) UNTIL (ch < "0") & (ch # ".") OR (ch > "9") & (CAP(ch) < "A") OR (CAP(ch) > "Z");
- id[i] := 0X
- END Ident;
- PROCEDURE Sym;
- VAR ch0: CHAR;
- BEGIN
- lastSym := sym; lastPos := pos; sym := none;
- WHILE sym = none DO
- CASE ch OF
- | 0X: sym := eot
- | 1X.." ": REPEAT IF ch = CR THEN lineBeg := pos END; Ch UNTIL (ch > " ") OR (ch = 0X)
- | "a".."z", "A".."Z": Ident;
- CASE id[0] OF
- | "A": IF id = "ARRAY" THEN sym := array END
- | "E": IF id = "END" THEN sym := end END
- | "P": IF id = "PROCEDURE" THEN sym := procedure ELSIF id = "POINTER" THEN sym := pointer END
- | "R": IF id = "RECORD" THEN sym := record END
- ELSE
- END;
- IF sym = ident THEN lastID := id; lastIDline := lineBeg END
- | "'", '"': ch0 := ch; REPEAT Ch UNTIL (ch = ch0) OR (ch < " ") OR R.eot; Ch
- | "(": Ch; IF ch = "*" THEN Ch; Comment ELSE sym := lparen END
- | ")": sym := rparen; Ch
- | ":": sym := colon; Ch
- | "=": sym := eql; Ch
- | ";": sym := semicolon; Ch
- | "^": sym := arrow; Ch
- | "*": sym := star; Ch
- ELSE Ch
- END
- END
- END Sym;
- (* parser *)
- PROCEDURE FindClass(VAR id: Name; VAR c: Class);
- BEGIN c := classes;
- WHILE (c # NIL) & (c.name # id) DO c := c.next END
- END FindClass;
- PROCEDURE FindLink(VAR id: Name; VAR c: Class);
- VAR p: Class;
- BEGIN p := classes;
- WHILE (p # NIL) & ((p.link = NIL) OR (p.link.name # id)) DO p := p.next END;
- IF p = NIL THEN c := NIL ELSE c := p.link END
- END FindLink;
- PROCEDURE RecordType(VAR c: Class);
- VAR ok: BOOLEAN; c0: Class;
- BEGIN c := NIL;
- ok := lastSym IN {eql, ident};
- IF lastSym = eql THEN FindLink(lastID, c) END;
- IF c = NIL THEN NEW(c); c.name := lastID; c.kind := record END;
- c.beg := lastIDline;
- LOOP Sym;
- IF sym IN {end, eot} THEN c.end := lastPos - 1; EXIT
- ELSIF sym = record THEN RecordType(c0) (*ignore nested records*)
- END
- END;
- IF ~ok THEN c := NIL END
- END RecordType;
- PROCEDURE PointerType(VAR c: Class);
- VAR ok: BOOLEAN; c0: Class;
- BEGIN
- ok := lastSym = eql;
- NEW(c); c.name := lastID; c.kind := pointer; c.beg := lastIDline;
- Sym; Sym;
- IF sym = ident THEN
- FindClass(id, c0);
- IF c0 = NIL THEN NEW(c0); c0.name := id; c0.kind := record END;
- c.link := c0; Sym; c.end := pos - 1;
- ELSIF sym = record THEN
- RecordType(c0); c.link := c0; c0.name := "";
- c.end := lastPos - 1;
- IF ok THEN c0.next := classes; classes := c0 END
- ELSE ok := FALSE
- END;
- IF ~ok THEN c := NIL END
- END PointerType;
- PROCEDURE Procedure;
- VAR m: Method; className: Name; c: Class;
- BEGIN
- NEW(m); m.beg := pos-10;
- Sym; IF sym # lparen THEN RETURN END;
- REPEAT Sym UNTIL sym IN {colon, eot};
- Sym; className := id;
- REPEAT Sym UNTIL sym IN {lparen, semicolon, eot};
- IF sym = lparen THEN REPEAT Sym UNTIL sym IN {rparen, eot};
- Sym; IF sym = colon THEN Sym; Sym END
- END;
- m.end := pos - 1;
- FindClass(className, c); IF c = NIL THEN RETURN END;
- IF c.kind = pointer THEN c := c.link END;
- m.next := c.methods; c.methods := m
- END Procedure;
- (* output routines *)
- PROCEDURE Wr(ch: CHAR);
- BEGIN Texts.Write(W, ch)
- END Wr;
- PROCEDURE Str(s: ARRAY OF CHAR);
- BEGIN Texts.WriteString(W, s)
- END Str;
- PROCEDURE Lead(pos: LONGINT): INTEGER;
- VAR n: INTEGER;
- BEGIN Start(pos); n := -1;
- REPEAT Ch; INC(n) UNTIL (ch > " ") OR (ch = CR) OR R.eot;
- RETURN n
- END Lead;
- PROCEDURE OutStretch(from, to: LONGINT; VAR ind, nLines: INTEGER; VAR leadCh: CHAR);
- VAR lead, i: INTEGER; pos: LONGINT;
- BEGIN
- lead := Lead(from); nLines := 0;
- REPEAT
- ind := Lead(from) - lead; INC(nLines);
- Start(from); FOR i := 1 TO lead DO Ch; INC(from) END;
- IF ch = " " THEN leadCh := " " ELSE leadCh := TAB END;
- pos := from;
- WHILE (from < to) & (ch # CR) DO Ch; INC(from) END;
- Texts.Append(TOut, W.buf);
- Texts.Save(TMod, pos, from, B); Texts.Append(TOut, B)
- UNTIL from >= to;
- END OutStretch;
- PROCEDURE OutMethod(m: Method; ind: INTEGER; leadCh: CHAR);
- VAR i, j: INTEGER; k: CHAR;
- BEGIN
- IF m # NIL THEN OutMethod(m.next, ind, leadCh);
- FOR i := 1 TO ind DO Wr(leadCh) END;
- OutStretch(m.beg, m.end, i, j, k); Wr(CR)
- END;
- END OutMethod;
- PROCEDURE OutClass(c: Class);
- VAR ind, nLines, i: INTEGER; leadCh: CHAR;
- BEGIN
- OutStretch(c.beg, c.end, ind, nLines, leadCh); Wr(CR);
- IF nLines = 1 THEN INC(ind) END;
- IF (c.kind = pointer) & (c.link # NIL) THEN
- IF c.link.name = "" THEN c := c.link ELSIF type # "" THEN OutClass(c.link); RETURN END
- END;
- IF c.kind = record THEN
- OutMethod(c.methods, ind, leadCh);
- Str("END;"); Wr(CR)
- END
- END OutClass;
- PROCEDURE OutAll(c: Class);
- BEGIN
- IF c # NIL THEN OutAll(c.next);
- IF c.name # "" THEN OutClass(c) END
- END
- END OutAll;
- (* main *)
- PROCEDURE PrepName(s: ARRAY OF CHAR; VAR mod, type: ARRAY OF CHAR);
- VAR i, j: INTEGER;
- BEGIN i := 0;
- REPEAT mod[i] := s[i]; INC(i) UNTIL (s[i-1] = 0X) OR (s[i-1] = ".");
- IF s[i-1] = "." THEN mod[i] := "M"; mod[i+1] := "o"; mod[i+2] := "d"; mod[i+3] := 0X;
- j := 0; REPEAT type[j] := s[i]; INC(i); INC(j) UNTIL s[i-1] = 0X
- ELSE COPY(mod, type); mod[0] := 0X
- END
- END PrepName;
- PROCEDURE Show*; (** ( "*" | "^" | name ) **)
- VAR S: Texts.Scanner; V: Viewers.Viewer; text: Texts.Text; Menu, Text: TextFrames.Frame; x, y: INTEGER;
- selbeg, selend, time: LONGINT; c: Class; m: Method; mod: Name;
- BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
- IF (S.class = Texts.Char) & (S.c = "*") & (S.line = 0) THEN V := Oberon.MarkedViewer();
- IF (V # NIL) & (V.dsc # NIL) & (V.dsc.next # NIL) & (V.dsc.next IS TextFrames.Frame) THEN
- TMod := V.dsc.next(TextFrames.Frame).text; type := ""
- ELSE RETURN
- END
- ELSIF (S.class = Texts.Name) & (S.line = 0) THEN
- PrepName(S.s, mod, type); TMod := TextFrames.Text(mod)
- ELSE Oberon.GetSelection(text, selbeg, selend, time);
- IF time > 0 THEN Texts.OpenScanner(S, text, selbeg); Texts.Scan(S);
- IF (S.class # Texts.Name) OR (S.line > 0) THEN RETURN END
- ELSE RETURN
- END;
- PrepName(S.s, mod, type);
- IF mod = "" THEN TMod := text ELSE TMod := TextFrames.Text(mod) END
- END;
- Start(0); Ch; sym := none; lineBeg := 0; lastID := ""; lastIDline := 0; lastSym := none; classes := NIL;
- LOOP Sym;
- CASE sym OF
- procedure: Procedure
- | record: RecordType(c); IF c # NIL THEN c.next := classes; classes := c END
- | pointer: PointerType(c); IF c # NIL THEN c.next := classes; classes := c END
- | eot: EXIT
- ELSE
- END
- END;
- TOut := TextFrames.Text(""); NEW(B); Texts.OpenBuf(B);
- Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
- IF type = "" THEN OutAll(classes)
- ELSE FindClass(type, c); IF c # NIL THEN OutClass(c) END
- END;
- Texts.Append(TOut, W.buf);
- V := MenuViewers.New(TextFrames.NewMenu(type, StdMenu), TextFrames.NewText(TOut, 0),
- TextFrames.menuH, x, y);
- TMod := NIL; TOut := NIL; B := NIL; classes := NIL
- END Show;
- BEGIN Texts.OpenWriter(W)
- END Class.
-